package org.ala.tcp_feign_client.context.heart;

import java.util.Iterator;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

import org.ala.tcp_feign_client.ITcpFeignClient;
import org.ala.tcp_feign_client.context.TcpFeignClientContext;
import org.ala.tcp_feign_common.exceptions.ActiveException;
import org.ala.tcp_feign_common.exceptions.LoginException;
import org.ala.tcp_feign_common.logs.LoggerFactory;
import org.ala.tcp_feign_common.msg.heart.HeartByteMessage;
import org.slf4j.Logger;


/**
 * 心跳定时任务
 *
 * @author 骆毅(ala)
 * @date 2024年4月20日
 */
public class HeartScheduled {

	
	static Logger log = LoggerFactory.getLogger("tcp-feign", "client");
	
	
	/**
	 * 心跳定时任务
	 */
	protected ScheduledExecutorService schedule;
	/**
	 * 心跳间隔
	 * <p>	单位：毫秒
	 * <p>	默认：10s
	 */
	protected long interval = 10000l;
	
	
	public HeartScheduled(long interval) {
		super();
		this.interval = interval;
	}


	/**
	 * 开启定时任务
	 */
	public void start() {
		if (schedule == null) {
			schedule = Executors.newScheduledThreadPool(1);
		}
		
		schedule.scheduleAtFixedRate(() -> heart(), interval, interval, TimeUnit.MILLISECONDS);
	}
	/**
	 * 心跳消息
	 */
	protected void heart() {
		Iterator<ITcpFeignClient> iterator = TcpFeignClientContext.instance().getActiveChannel().values().iterator();
		while (iterator.hasNext()) {
			ITcpFeignClient client = iterator.next();
			if (!client.isActive()) {
				log.warn("[HeartScheduled heart] 心跳检测时发现链接不可用，该链接可能还没被正式启用. client:" + client);
				continue;
			}
			
			int isLogin = client.isLogin();
			if (isLogin < 0) {
				log.warn("[HeartScheduled heart] 心跳检测时发现链接登录失败，可能是用户名密码配错了，来个人管管. client:" + client);
				continue;
			}
			if (isLogin == 0) {
				//	取3次握手时间戳
				long connectTimestamp = client.connectTimestamp();
				//	如果握手时间戳取不到，说明该链接握手还为成功
				if (connectTimestamp < 0) {
					log.warn("[HeartScheduled heart] 心跳检测时发现链接3次握手不成功，该链接可能还没被正式启用，本次心跳就不发了. client:" + client);
				}
				//	如果还在等登录消息，但握手时间戳在允许的时间范围内，继续等待
				else if (System.currentTimeMillis() - connectTimestamp < interval) {
					log.warn("[HeartScheduled heart] 心跳检测时发现链接还在等待登录回执，本次心跳就不发了. client:" + client);
				} 
				//	如果还在等登录消息，但握手时间戳已经超过最大允许时间范围，可能服务端没响应此次登录消息，重发登录消息
				else {
					log.warn("[HeartScheduled heart] 心跳检测时发现链接还在等待登录回执，但时间已经超时了，将此链接放入重连队列. client:" + client);
					try {
						client.sendLogin(client.username(), client.password());
					} catch (ActiveException e) {
						log.warn("[HeartScheduled heart] 链接出现异常，但有可能是已经弃用的连接，等待业务方关闭 client:" + client);
					}
				}
				continue;
			}
			
			try {
				client.send(HeartByteMessage.build());
			} catch (ActiveException e) {
				log.warn("[HeartScheduled heart] 发送心跳消息异常，链接已失效. ", e);
			} catch (LoginException e) {
				log.warn("[HeartScheduled heart] 发送心跳消息异常，链接未登录. ", e);
			}
		}
	}
}
